using System;
using System.Collections.Generic;
using System.Text;
using Weazel.Microblaze.Simulator.Engine;

namespace Weazel.Microblaze.Simulator.Components.Microblaze.Instructions
{
    public class Beqi
      : ConditionalBranchInstruction
    {
        private enum BeqiInstructionKind
        {
            None,
            beqi,
            beqid
        }

        private BeqiInstructionKind kind;

        public override int CycleCount
        {
            get
            {
                if (BranchStatus == BranchInstructionCycleCountStatus.BranchTaken)
                    return 1;
                else
                    return kind == BeqiInstructionKind.beqid ? 2 : 3;
            }        
        }

        public Beqi()
            : base("beqi")
        {
        }

        public override void Set(uint address, uint value)            
        {
            base.Set(address, value);

            kind =
              (DestinationRegister & 0x1F) == 0x10 ? BeqiInstructionKind.beqid :
              (DestinationRegister & 0x1F) == 0x00 ? BeqiInstructionKind.beqi :
              BeqiInstructionKind.None;

            if (kind == BeqiInstructionKind.None)
                throw new UnknownInstructionException(value);
        }

        public override void Execute(MicroblazeComponent MicroblazeComponent)
        {
            uint sa = MicroblazeComponent.ReadRegister(SourceRegisterA);

            if (sa == 0)
            {
                MicroblazeComponent.Pc = MicroblazeComponent.Pc + GetImmediateValue(MicroblazeComponent);
                BranchStatus = BranchInstructionCycleCountStatus.BranchTaken;

                if (kind == BeqiInstructionKind.beqid)
                    MicroblazeComponent.DelayedBranchActive = true;
            }
            else
            {
                MicroblazeComponent.Pc += 4;
                BranchStatus = BranchInstructionCycleCountStatus.BranchNotTaken;
            }
        }

        public override string ToString()
        {
            return String.Format("{0} r{1}, {2}",
              kind,
              SourceRegisterA,
              ImmediateValue
            );
        }
    }
}
